#pragma once 

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <string>
#include <vector>
#include <iostream>


#include "ConnetInfo.hpp"
#include "Tool.hpp"
using namespace std;
//我自己的数据信息
class Myself 
{
    public:
        string nick_name_;
        string school_;
        string passwd_;
        uint32_t user_id_;
};


class ChatClient
{
    public:
        ChatClient()
        {
            tcp_sock_ = -1;
            udp_sock_ = -1;
        }
        ChatClient(string& ip)
        {
            ip_ = ip;
        }
        ~ChatClient()
        {

        }
        int CreateSock()
        {
            tcp_sock_ = socket(AF_INET,SOCK_STREAM,0);
            if(tcp_sock_ < 0)
            {
                return -1;
            }
            udp_sock_ = socket(AF_INET,SOCK_DGRAM,0);
            if(udp_sock_ < 0)
            {
                return -1;
            }
            return 0;
        }
        int ConnectoSvr()
        {
            struct sockaddr_in dest_addr;
            dest_addr.sin_family = AF_INET;
            dest_addr.sin_port = htons(TCP_PORT);
            dest_addr.sin_addr.s_addr = inet_addr(ip_.c_str());
            int ret = connect(tcp_sock_,(struct sockaddr*)&dest_addr,sizeof(dest_addr));
            if(ret < 0)
            {
                return -1;
            }
            return 0;
        }
        int CreateAddConnect()
        {
            //创建套接字
            int ret = CreateSock();
            if(ret < 0)
            {
                return -1;
            }
            //连接服务器
            ret = ConnectoSvr();
            if(ret < 0)
            {
                return -1;
            }
            return 0;

        }

        int RegistertoSvr()
        {
            int ret = CreateAddConnect();
            if(ret < 0)
            {
                return -1;
            }

            //发送第一个tcp数据包
            char statu = Register;
            ssize_t send_size = send(tcp_sock_,&statu,1,0);
            if(send_size < 0)
            {
                return -1;
            }
            //发送第二个注册数据包
            RegisterInfo ri;
            cout << "please enter your name" << endl;
            fflush(stdout);
            cin >> ri.name;
            me_.nick_name_ = ri.name;
            cout << "please enter your school" << endl;
            fflush(stdout);
            cin >> ri.school;
            me_.school_ = ri.school;
            string first_passwd;
            string second_passwd;
            while(1)
            {
                cout << "please enter your passwd" << endl;
                fflush(stdout);
                cin >> first_passwd;
                cout << "please retry your passwd" << endl;
                fflush(stdout);
                cin >> second_passwd;
                if(first_passwd == second_passwd)
                {
                    strcpy(ri.passwd,first_passwd.c_str());
                    me_.passwd_ = first_passwd; 
                    break;
                }
            }
            UdpMsg* um = new UdpMsg();
            um->nick_name_ = me_.nick_name_;
            um->school_ = me_.school_;
            vec_.push_back(*um);
            send_size = send(tcp_sock_,&ri,sizeof(ri),0);
            if(send_size < 0)
            {
                return -1;
            }
            //接收应答
            ReplyInfo reply;
            ssize_t recv_size = recv(tcp_sock_,&reply,sizeof(reply),0);
            me_.user_id_ = reply.id_;
            LOG(INFO,"id") << me_.user_id_ << endl;
            if(recv_size < 0)
            {
                Closefd();
                return -1;
            }
            else if(recv_size == 0)
            {
                Closefd();
                return -1;
            }
            //正常
            if(reply.resp_state != Register_Success)
            {
                return -1;
            }
            return 0;

        }
        int LogintoSvr()
        {
            //创建套接字+连接服务器
            int ret = CreateAddConnect();
            if(ret < 0)
            {
                return -1;
            }
            //发送登录选择包
            char select = Login;
            ssize_t send_size = send(tcp_sock_,&select,1,0);
            if(send_size < 0)
            {
                return -1;
            }
            //发送登录数据包
            LoginInfo li;
            li.id_ = me_.user_id_;
            strncpy(li.passwd,me_.passwd_.c_str(),sizeof(li.passwd));
            send_size = send(tcp_sock_,&li,sizeof(li),0);
            if(send_size < 0)
            {
                return -1;
            }
            //正常发送之后
            //接收回复
            ReplyInfo ri;
            ssize_t recv_size = recv(tcp_sock_,&ri,sizeof(ri),0);
            if(recv_size < 0)
            {
                return -1;
            }
            else if(recv_size == 0)
            {
                Closefd();
                return -1; 
            }
            //正常收到接收的信息
            if(ri.resp_state != Login_Success)
            {
                return -1;
            }
            return 0;
            
        }
        int SendMsg(string& send_msg)
        {
           struct sockaddr_in addr;
           addr.sin_family = AF_INET;
           addr.sin_port = htons(UDP_PROT);
           addr.sin_addr.s_addr = inet_addr(ip_.c_str());
           //发送数据
           ssize_t sendto_size = sendto(udp_sock_,send_msg.c_str(),send_msg.size(),0,(struct sockaddr*)&addr,sizeof(addr));
           if(sendto_size < 0)
           {
               return -1;
           }
        }
        int RecvMsg(string* msg)
        {
           UdpMsg udp_msg;
           //接收数据
           char buf[UDP_COUNT]={0};
           ssize_t recv_size = recvfrom(udp_sock_,buf,sizeof(buf)-1,0,NULL,NULL);
           if(recv_size < 0)
           {
               return -1;
           }
           else if(recv_size == 0)
           {
                Closefd();
               return -1;
           }
           //正常接收到
           string recv_string;
           recv_string.assign(buf,strlen(buf));
           udp_msg.DeSerialize(recv_string);
           recv_string.clear();
           recv_string += udp_msg.nick_name_;
           recv_string += "-";
           recv_string += udp_msg.school_;
           recv_string += ":";
           recv_string += udp_msg.msg_;
           *msg = recv_string;
        }
        void Closefd()
        {
            if(tcp_sock_ > 0)
            {
                close(tcp_sock_);
            }
            tcp_sock_ = -1;
        }
        Myself& GetMe()
        {
            return me_;
        }

        vector<UdpMsg> GetVec()
        {
            return vec_;
        }
    private:
        int tcp_sock_;
        int udp_sock_;
        Myself me_;
        string ip_;
        vector<UdpMsg> vec_;
};
